#include "count.h"
#include "traverse.h"
#include "tree_basic.h"
#include "dbug.h"
#include "memory.h"
#include "globals.h"
#include "ctinfo.h"

struct INFO {
    int add, sub, mul, div, mod;
};

#define INFO_ADD(n) ((n)->add)
#define INFO_SUB(n) ((n)->sub)
#define INFO_MUL(n) ((n)->mul)
#define INFO_DIV(n) ((n)->div)
#define INFO_MOD(n) ((n)->mod)

static info *MakeInfo()
{
  info *result = MEMmalloc(sizeof(info));

  INFO_ADD(result) = 0;
  INFO_SUB(result) = 0;
  INFO_MUL(result) = 0;
  INFO_DIV(result) = 0;
  INFO_MOD(result) = 0;

  return result;
}


static info *FreeInfo( info *info)
{
  return MEMfree( info);
}

node *
COUNTbinop (node * arg_node, info * arg_info)
{
  DBUG_ENTER ("COUNTbinop");

  switch (BINOP_OP( arg_node)) {
    case BO_add:
      INFO_ADD(arg_info)++;
      break;
    case BO_sub:
      INFO_SUB(arg_info)++;
      break;
    case BO_mul:
      INFO_MUL(arg_info)++;
      break;
    case BO_div:
      INFO_DIV(arg_info)++;
      break;
    case BO_mod:
      INFO_MOD(arg_info)++;
      break;
    case BO_unknown:
      DBUG_ASSERT( 0, "unknown binop detected!");
  }
  arg_node = TRAVcont(arg_node, arg_info);
  DBUG_RETURN (arg_node);
}

node
*COUNTdoCount( node *syntaxtree)
{
  info *info;

  DBUG_ENTER("COUNTdoCount");

  DBUG_ASSERT( (syntaxtree!= NULL), "COUNTdoCount called with empty syntaxtree");

  info = MakeInfo();

  TRAVpush( TR_count);

  syntaxtree = TRAVdo( syntaxtree, info);

  TRAVpop();

  CTInote("Add: %d\nSub: %d\nMul: %d\nDiv: %d\nMod: %d\n", INFO_ADD(info), INFO_SUB(info), INFO_MUL(info), INFO_DIV(info), INFO_MOD(info));

  info = FreeInfo(info);

  DBUG_RETURN( syntaxtree);
}
